﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Platform.ObjectModel;
//using IQToolkit;
//using IQToolkit.Data;
using Platform.Infrastructure;

namespace Platform.Storage
{
	// Custom LINQ Provider http://msdn.microsoft.com/en-us/library/bb882640.aspx
	// LINQ Providers	http://blogs.msdn.com/b/charlie/archive/2008/02/28/link-to-everything-a-list-of-linq-providers.aspx
	//					http://blogs.msdn.com/b/charlie/archive/2006/10/05/links-to-linq.aspx
	//		http://json.codeplex.com/
	// LINQ extender	http://linqextender.codeplex.com/
	

	// Outro tipo de repositório 
	// https://cloudant.com

	/// <summary>
	/// Acesso ao repositório de documentos do sistema
	/// </summary>
	public interface ILibraryStorage : IDisposable
	{
		/// <summary>
		/// Chamado 
		/// </summary>
		/// <param name="library"></param>
		void Init( Library library );

		/// <summary>
		/// Obtém o que a implementação do repositório pode fazer
		/// </summary>
		SearchStorageCapabilities Capabilities
		{ get; }

		/// <summary>
		/// Obtém o objeto para fazer pesquisa por objetos dinâmicos
		/// </summary>
		/// <typeparam name="TData"></typeparam>
		/// <returns></returns>
		IQueryable<TData> Get<TData>()
			where TData : DataObjectFlake;

		/// <summary>
		/// Realiza a exclusão de um documento do repositório
		/// </summary>
		/// <param name="tokenID"></param>
		[Obsolete( "Passar o contexto de execução para o método \"Remove\"." )]
		void Remove( DocumentToken tokenID );

		/// <summary>
		/// Adiciona ou atualiza o documento no repositório
		/// </summary>
		/// <param name="context"></param>
		void InsertOrUpdate( DocumentContext context );

		/*
		 * PARA A PESQUISA
		 * 
-- Relation (deve ser armazenado somente a navegação que contém o menor número de elementos)
select 'Catalog.Product[EComm.Brand]' AS Property, 'P-001' AS SourceToken, 'BRAND-001' AS DestToken
select 'Catalog.Category[EComm.Product]' AS Property, 'C-001' AS SourceToken, 'P-001' AS DestToken
select 'Catalog.Category[EComm.Product]' AS Property, 'C-001' AS SourceToken, 'P-00N' AS DestToken

-- PropertyValue (as binary)
select 'Catalog.Product[EComm.Name]' AS Property, 'P-001' AS Token, 0x010101 AS Value

-- PropertyIndex (string)
select 'Catalog.Product[EComm.Name]' AS Property, 'P-001' AS SourceToken, 'iphone' AS Value

-- PropertyIndex (number)
select 'Catalog.Product[EComm.Price]' AS Property, 'P-001' AS SourceToken, 10 AS Value

-- PropertyIndex (DateTime)
select 'Catalog.Product[EComm.CreateDate]' AS Property, 'P-001' AS SourceToken, GETDATE() AS Value 
		 */
	}

	/// <summary>
	/// 
	/// </summary>
	public interface ILibraryStorageFactory
	{
		ILibraryStorage Create();
	}


	public sealed class DefaultLibraryStorageFactory : ILibraryStorageFactory
	{
		private Func<ILibraryStorage> creator;

		public DefaultLibraryStorageFactory( Func<ILibraryStorage> creator )
		{
			Arguments.IsNotNull( "creator", creator );
			this.creator = creator;
		}

		#region ILibraryStorageFactory Members

		public ILibraryStorage Create()
		{
			return this.creator();
		}

		#endregion
	}
}
